package com.kitbox.hl.meshow.common.utils.file;

import com.kitbox.hl.meshow.common.utils.datetime.DateUtil;
import com.kitbox.hl.meshow.common.utils.string.StringUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.*;


/**
 * 文件处理工具类
 * 
 * @author caozj
 */
public class FileUtil extends FileUtils{

	/**
	 * 创建目录
	 * 
	 * @param filePath
	 *            - 源文件(可以是文件,也可以是目录)
	 */
	public static void mkdirs(String filePath) {
		if (StringUtils.isBlank(filePath)) {
			return;
		}
		if (filePath.indexOf(".") != -1) {// 可能是文件
			filePath = filePath.substring(0, filePath.lastIndexOf("/"));
		}
		File file = new File(filePath);
		if (!file.exists()) {
			file.mkdirs();
		}
	}

	/**
	 * copy文件 1. 请确认目标文件所在目录是否存在 2. 请确认当前用户是否有写权限
	 * 
	 * @param inPath
	 *            - 源文件(绝对路径)
	 * @param outPath
	 *            - 目标文件
	 */
	public static void copy(String inPath, String outPath) {
		InputStream is = null;
		OutputStream os = null;
		try {
			is = new FileInputStream(new File(inPath));
			os = new FileOutputStream(new File(outPath));
			IOUtils.copy(is, os);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			IOUtils.closeQuietly(is);
			IOUtils.closeQuietly(os);
		}
	}

	/**
	 * copy文件 1. 请确认目标文件所在目录是否存在 2. 请确认当前用户是否有写权限
	 * 
	 * @param inFile
	 *            - 源文件
	 * @param outPath
	 *            - 目标文件
	 */
	public static void copy(File inFile, String outPath) {
		InputStream is = null;
		OutputStream os = null;
		try {
			is = new FileInputStream(inFile);
			os = new FileOutputStream(new File(outPath));
			IOUtils.copy(is, os);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			IOUtils.closeQuietly(is);
			IOUtils.closeQuietly(os);
		}
	}

	/**
	 * copy文件 1. 请确认目标文件所在目录是否存在 2. 请确认当前用户是否有写权限
	 * 
	 * @param is
	 *            - 源文件流
	 * @param outPath
	 *            - 目标文件
	 */
	public static void copy(InputStream is, String outPath) {
		OutputStream os = null;
		try {
			os = new FileOutputStream(new File(outPath));
			IOUtils.copy(is, os);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			IOUtils.closeQuietly(is);
			IOUtils.closeQuietly(os);
		}
	}

	/**
	 * 获取文件的扩展名
	 * 
	 * @param fileName
	 *            文件名
	 * @return
	 */
	public static String getFileExt(String fileName) {
		int index = fileName.lastIndexOf(".");
		String ext = StringUtils.EMPTY;
		if (index > -1) {
			ext = fileName.substring(index + 1);
		}
		return ext;
	}

	/**
	 * 获取所有文件名称
	 * @param path
	 * @param //fileName
	 */
	public static List<String> getAllFileName(String path)
    {
		List<String> fileNameList = new ArrayList<String>();
		
        File file = new File(path);
        File [] files = file.listFiles();
        
        for(File a:files)
        {
            if(!a.isDirectory())
            {
                fileNameList.add(a.getName());
            }
        }
        
        return fileNameList;
    }

//	/**
//	 * NIO way
//	 */
//	public static byte[] toByteArray(String filename) {
//
//		File f = new File(filename);
//		if (!f.exists()) {
//			//log.error("文件未找到！" + filename);
//			throw new RuntimeException("FILE_NOT_FOUND");
//		}
//		FileChannel channel = null;
//		FileInputStream fs = null;
//		try {
//			fs = new FileInputStream(f);
//			channel = fs.getChannel();
//			ByteBuffer byteBuffer = ByteBuffer.allocate((int) channel.size());
//			while ((channel.read(byteBuffer)) > 0) {
//				// do nothing
//				// System.out.println("reading");
//			}
//			return byteBuffer.array();
//		} catch (IOException e) {
//			throw new RuntimeException("FILE_READING_ERROR");
//		} finally {
//			try {
//				channel.close();
//			} catch (IOException e) {
//				throw new RuntimeException("FILE_READING_ERROR");
//			}
//			try {
//				fs.close();
//			} catch (IOException e) {
//				throw new RuntimeException("FILE_READING_ERROR");
//			}
//		}
//	}

//	/**
//	 * 删除目录
//	 *
//	 * @author fengshuonan
//	 * @Date 2017/10/30 下午4:15
//	 */
//	public static boolean deleteDir(File dir) {
//		if (dir.isDirectory()) {
//			String[] children = dir.list();
//			for (int i = 0; i < children.length; i++) {
//				boolean success = deleteDir(new File(dir, children[i]));
//				if (!success) {
//					return false;
//				}
//			}
//		}
//		return dir.delete();
//	}



	private static Logger log = LoggerFactory.getLogger(FileUtil.class);

	/**
	 * NIO way
	 */
	public static byte[] toByteArray(String filename) {

		File f = new File(filename);
		if (!f.exists()) {
			log.error("文件未找到！" + filename);
			throw new RuntimeException("FILE_NOT_FOUND");
		}
		FileChannel channel = null;
		FileInputStream fs = null;
		try {
			fs = new FileInputStream(f);
			channel = fs.getChannel();
			ByteBuffer byteBuffer = ByteBuffer.allocate((int) channel.size());
			while ((channel.read(byteBuffer)) > 0) {
				// do nothing
				// System.out.println("reading");
			}
			return byteBuffer.array();
		} catch (IOException e) {
			throw new RuntimeException("FILE_READING_ERROR");
		} finally {
			try {
				channel.close();
			} catch (IOException e) {
				throw new RuntimeException("FILE_READING_ERROR");
			}
			try {
				fs.close();
			} catch (IOException e) {
				throw new RuntimeException("FILE_READING_ERROR");
			}
		}
	}









	/*以下来源于代码生成*/

	/**
	 * 获取随机位数的字符串
	 *
	 * @author fengshuonan
	 * @Date 2017/8/24 14:09
	 */
	public static String getRandomString(int length) {
		String base = "abcdefghijklmnopqrstuvwxyz0123456789";
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < length; i++) {
			int number = random.nextInt(base.length());
			sb.append(base.charAt(number));
		}
		return sb.toString();
	}

	/**
	 * 判断一个对象是否是时间类型
	 *
	 * @author stylefeng
	 * @Date 2017/4/18 12:55
	 */
	public static String dateType(Object o) {
		if (o instanceof Date) {
			return DateUtil.getDay((Date) o);
		} else {
			return o.toString();
		}
	}

	/**
	 * 获取异常的具体信息
	 *
	 * @author fengshuonan
	 * @Date 2017/3/30 9:21
	 * @version 2.0
	 */
	public static String getExceptionMsg(Exception e) {
		StringWriter sw = new StringWriter();
		try {
			e.printStackTrace(new PrintWriter(sw));
		} finally {
			try {
				sw.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
		return sw.getBuffer().toString().replaceAll("\\$", "T");
	}

	/**
	 * 比较两个对象是否相等。<br>
	 * 相同的条件有两个，满足其一即可：<br>
	 * 1. obj1 == null && obj2 == null; 2. obj1.equals(obj2)
	 *
	 * @param obj1 对象1
	 * @param obj2 对象2
	 * @return 是否相等
	 */
	public static boolean equals(Object obj1, Object obj2) {
		return (obj1 != null) ? (obj1.equals(obj2)) : (obj2 == null);
	}

	/**
	 * 计算对象长度，如果是字符串调用其length函数，集合类调用其size函数，数组调用其length属性，其他可遍历对象遍历计算长度
	 *
	 * @param obj 被计算长度的对象
	 * @return 长度
	 */
	public static int length(Object obj) {
		if (obj == null) {
			return 0;
		}
		if (obj instanceof CharSequence) {
			return ((CharSequence) obj).length();
		}
		if (obj instanceof Collection) {
			return ((Collection<?>) obj).size();
		}
		if (obj instanceof Map) {
			return ((Map<?, ?>) obj).size();
		}

		int count;
		if (obj instanceof Iterator) {
			Iterator<?> iter = (Iterator<?>) obj;
			count = 0;
			while (iter.hasNext()) {
				count++;
				iter.next();
			}
			return count;
		}
		if (obj instanceof Enumeration) {
			Enumeration<?> enumeration = (Enumeration<?>) obj;
			count = 0;
			while (enumeration.hasMoreElements()) {
				count++;
				enumeration.nextElement();
			}
			return count;
		}
		if (obj.getClass().isArray() == true) {
			return Array.getLength(obj);
		}
		return -1;
	}

	/**
	 * 对象中是否包含元素
	 *
	 * @param obj     对象
	 * @param element 元素
	 * @return 是否包含
	 */
	public static boolean contains(Object obj, Object element) {
		if (obj == null) {
			return false;
		}
		if (obj instanceof String) {
			if (element == null) {
				return false;
			}
			return ((String) obj).contains(element.toString());
		}
		if (obj instanceof Collection) {
			return ((Collection<?>) obj).contains(element);
		}
		if (obj instanceof Map) {
			return ((Map<?, ?>) obj).values().contains(element);
		}

		if (obj instanceof Iterator) {
			Iterator<?> iter = (Iterator<?>) obj;
			while (iter.hasNext()) {
				Object o = iter.next();
				if (equals(o, element)) {
					return true;
				}
			}
			return false;
		}
		if (obj instanceof Enumeration) {
			Enumeration<?> enumeration = (Enumeration<?>) obj;
			while (enumeration.hasMoreElements()) {
				Object o = enumeration.nextElement();
				if (equals(o, element)) {
					return true;
				}
			}
			return false;
		}
		if (obj.getClass().isArray() == true) {
			int len = Array.getLength(obj);
			for (int i = 0; i < len; i++) {
				Object o = Array.get(obj, i);
				if (equals(o, element)) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * 对象是否不为空(新增)
	 *
	 * @param //obj String,List,Map,Object[],int[],long[]
	 * @return
	 */
	public static boolean isNotEmpty(Object o) {
		return !isEmpty(o);
	}

	/**
	 * 对象是否为空
	 *
	 * @param //obj String,List,Map,Object[],int[],long[]
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static boolean isEmpty(Object o) {
		if (o == null) {
			return true;
		}
		if (o instanceof String) {
			if (o.toString().trim().equals("")) {
				return true;
			}
		} else if (o instanceof List) {
			if (((List) o).size() == 0) {
				return true;
			}
		} else if (o instanceof Map) {
			if (((Map) o).size() == 0) {
				return true;
			}
		} else if (o instanceof Set) {
			if (((Set) o).size() == 0) {
				return true;
			}
		} else if (o instanceof Object[]) {
			if (((Object[]) o).length == 0) {
				return true;
			}
		} else if (o instanceof int[]) {
			if (((int[]) o).length == 0) {
				return true;
			}
		} else if (o instanceof long[]) {
			if (((long[]) o).length == 0) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 对象组中是否存在 Empty Object
	 *
	 * @param os 对象组
	 * @return
	 */
	public static boolean isOneEmpty(Object... os) {
		for (Object o : os) {
			if (isEmpty(o)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 对象组中是否全是 Empty Object
	 *
	 * @param os
	 * @return
	 */
	public static boolean isAllEmpty(Object... os) {
		for (Object o : os) {
			if (!isEmpty(o)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 是否为数字
	 *
	 * @param obj
	 * @return
	 */
	public static boolean isNum(Object obj) {
		try {
			Integer.parseInt(obj.toString());
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	/**
	 * 如果为空, 则调用默认值
	 *
	 * @param str
	 * @return
	 */
	public static Object getValue(Object str, Object defaultValue) {
		if (isEmpty(str)) {
			return defaultValue;
		}
		return str;
	}

	/**
	 * 格式化文本
	 *
	 * @param template 文本模板，被替换的部分用 {} 表示
	 * @param values   参数值
	 * @return 格式化后的文本
	 */
	public static String format(String template, Object... values) {
		return StringUtil.format(template, values);
	}

	/**
	 * 格式化文本
	 *
	 * @param template 文本模板，被替换的部分用 {key} 表示
	 * @param map      参数值对
	 * @return 格式化后的文本
	 */
	public static String format(String template, Map<?, ?> map) {
		return StringUtil.format(template, map);
	}

	/**
	 * 强转->string,并去掉多余空格
	 *
	 * @param str
	 * @return
	 */
	public static String toStr(Object str) {
		return toStr(str, "");
	}

	/**
	 * 强转->string,并去掉多余空格
	 *
	 * @param str
	 * @param defaultValue
	 * @return
	 */
	public static String toStr(Object str, String defaultValue) {
		if (null == str) {
			return defaultValue;
		}
		return str.toString().trim();
	}

	/**
	 * 强转->int
	 *
	 * @param obj
	 * @return
	 */
//	public static int toInt(Object value) {
//		return toInt(value, -1);
//	}

	/**
	 * 强转->int
	 *
	 * @param obj
	 * @param defaultValue
	 * @return
	 */
//	public static int toInt(Object value, int defaultValue) {
//		return Convert.toInt(value, defaultValue);
//	}

	/**
	 * 强转->long
	 *
	 * @param obj
	 * @return
	 */
//	public static long toLong(Object value) {
//		return toLong(value, -1);
//	}

	/**
	 * 强转->long
	 *
	 * @param obj
	 * @param defaultValue
	 * @return
	 */
//	public static long toLong(Object value, long defaultValue) {
//		return Convert.toLong(value, defaultValue);
//	}
//
//	public static String encodeUrl(String url) {
//		return URLKit.encode(url, CharsetKit.UTF_8);
//	}
//
//	public static String decodeUrl(String url) {
//		return URLKit.decode(url, CharsetKit.UTF_8);
//	}

	/**
	 * map的key转为小写
	 *
	 * @param map
	 * @return Map<String , Object>
	 */
	public static Map<String, Object> caseInsensitiveMap(Map<String, Object> map) {
		Map<String, Object> tempMap = new HashMap<>();
		for (String key : map.keySet()) {
			tempMap.put(key.toLowerCase(), map.get(key));
		}
		return tempMap;
	}

	/**
	 * 获取map中第一个数据值
	 *
	 * @param <K> Key的类型
	 * @param <V> Value的类型
	 * @param map 数据源
	 * @return 返回的值
	 */
	public static <K, V> V getFirstOrNull(Map<K, V> map) {
		V obj = null;
		for (Map.Entry<K, V> entry : map.entrySet()) {
			obj = entry.getValue();
			if (obj != null) {
				break;
			}
		}
		return obj;
	}

	/**
	 * 创建StringBuilder对象
	 *
	 * @return StringBuilder对象
	 */
	public static StringBuilder builder(String... strs) {
		final StringBuilder sb = new StringBuilder();
		for (String str : strs) {
			sb.append(str);
		}
		return sb;
	}

	/**
	 * 创建StringBuilder对象
	 *
	 * @return StringBuilder对象
	 */
	public static void builder(StringBuilder sb, String... strs) {
		for (String str : strs) {
			sb.append(str);
		}
	}

	/**
	 * 去掉指定后缀
	 *
	 * @param str    字符串
	 * @param suffix 后缀
	 * @return 切掉后的字符串，若后缀不是 suffix， 返回原字符串
	 */
	public static String removeSuffix(String str, String suffix) {
		if (isEmpty(str) || isEmpty(suffix)) {
			return str;
		}

		if (str.endsWith(suffix)) {
			return str.substring(0, str.length() - suffix.length());
		}
		return str;
	}

	/**
	 * 当前时间
	 *
	 * @author stylefeng
	 * @Date 2017/5/7 21:56
	 */
	public static String currentTime() {
		return null;
	}

	/**
	 * 首字母大写
	 *
	 * @author stylefeng
	 * @Date 2017/5/7 22:01
	 */
	public static String firstLetterToUpper(String val) {
		return StringUtil.firstCharToUpperCase(val);
	}

	/**
	 * 首字母小写
	 *
	 * @author stylefeng
	 * @Date 2017/5/7 22:02
	 */
	public static String firstLetterToLower(String val) {
		return StringUtil.firstCharToLowerCase(val);
	}

	/**
	 * 判断是否是windows操作系统
	 *
	 * @author stylefeng
	 * @Date 2017/5/24 22:34
	 */
	public static Boolean isWinOs() {
		String os = System.getProperty("os.name");
		if (os.toLowerCase().startsWith("win")) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 获取临时目录
	 *
	 * @author stylefeng
	 * @Date 2017/5/24 22:35
	 */
	public static String getTempPath() {
		return System.getProperty("java.io.tmpdir");
	}

	/**
	 * 把一个数转化为int
	 *
	 * @author fengshuonan
	 * @Date 2017/11/15 下午11:10
	 */
	public static Integer toInt(Object val) {
		if (val instanceof Double) {
			BigDecimal bigDecimal = new BigDecimal((Double) val);
			return bigDecimal.intValue();
		} else {
			return Integer.valueOf(val.toString());
		}

	}

	/**
	 * 获取项目路径
	 */
	public static String getWebRootPath(String filePath) {
		try {
			String path = FileUtil.class.getClassLoader().getResource("").toURI().getPath();
			path = path.replace("/WEB-INF/classes/", "");
			path = path.replace("/target/classes/", "");
			path = path.replace("file:/", "");
			if (isEmpty(filePath)) {
				return path;
			} else {
				return path + "/" + filePath;
			}
		} catch (URISyntaxException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 获取文件后缀名 不包含点
	 */
	public static String getFileSuffix(String fileWholeName) {
		if (isEmpty(fileWholeName)) {
			return "none";
		}
		int lastIndexOf = fileWholeName.lastIndexOf(".");
		return fileWholeName.substring(lastIndexOf + 1);
	}




	/**
	 * 删除目录
	 *
	 * @author fengshuonan
	 * @Date 2017/10/30 下午4:15
	 */
	public static boolean deleteDir(File dir) {
		if (dir.isDirectory()) {
			String[] children = dir.list();
			for (int i = 0; i < children.length; i++) {
				boolean success = deleteDir(new File(dir, children[i]));
				if (!success) {
					return false;
				}
			}
		}
		return dir.delete();
	}



}
